import store from '../store'
import { v4 as uuid } from 'uuid'
import { getAnnexIntroductionNumber } from './dom'
import { refreshTableNumbers } from '@/utils/plugins/table/noteSetting'
import { refreshFigureNumbers } from '@/utils/plugins/image/figureSetting'
import tinymce from 'tinymce'
import { Message } from 'element-ui'
import { checkBeforeInsert } from '@/utils/helpers'

function setNewIds(el, editor) {
  editor.dom.setAttrib(el, 'data-id', uuid())

  if (el.dataset.noteId) {
    editor.dom.setAttrib(el, 'data-note-id', uuid())
  }
  if (el.dataset.blockId) {
    editor.dom.setAttrib(el, 'data-block-id', uuid())
  }
  if (el.dataset.referId) {
    editor.dom.setAttrib(el, 'data-refer-id', uuid())
  }
  if (el.dataset.referredId) {
    editor.dom.setAttrib(el, 'data-referred-id', uuid())
  }
  if (el.dataset.shareId) {
    editor.dom.setAttrib(el, 'data-share-id', uuid())
  }
  if (el.dataset.groupId) {
    editor.dom.setAttrib(el, 'data-group-id', uuid())
  }
  return el
}

function updateCmosDocFragment(el, editor) {
  editor.dom.setAttrib(el, 'style', '')
  setNewIds(el, editor)

  el.querySelectorAll('[data-id]').forEach((i) => {
    if (i.dataset.id) {
      editor.dom.setAttrib(i, 'style', '')
      setNewIds(i, editor)
    }
  })
}

function generateTableCaptionStr(annexNumber) {
  // 从外部粘贴的表格
  let str = `
      <caption class="table_caption zh">
        <p class="caption zh" ${annexNumber ? `data-table-annex-number="${annexNumber}"` : ''}>表题</p>
        <p class="unit"><br></p>
      </caption>
    `
  if (store.getters.languageType === 'both') {
    str += `
        <caption class="table_caption en">
          <p class="caption en" ${annexNumber ? `data-table-annex-number="${annexNumber}"` : ''}
            >Table title</p>
          <p class="unit"><br></p>
        </caption>
      `
  }
  return str
}
function generateFigureCaptionStr(annexNumber) {
  // 从外部粘贴的表格
  const dfan = annexNumber ? `data-figure-annex-number="${annexNumber}"` : ''
  let str = `<p class="data-content-image-caption zh" ${dfan} data-id="${uuid()}">图题</p>`
  if (store.getters.languageType === 'both') {
    str += `<p class="data-content-image-caption en" data-id="${uuid()}">xxx</p>`
  }
  return str
}

function generateBlockStr(el) {
  if (tinymce.DOM.is(el, 'p')) {
    return `<p data-id="${uuid()}" data-block-id="${uuid()}" data-type="paragraph">${el.textContent || '<br>'}</p>`
  }
  if (tinymce.DOM.is(el, 'div')) {
    return replacePara(el, tinymce.activeEditor)
  }
  console.debug('-----generateBlockStr error----')
  return ''
}

function generateTableTdStr(td, isTh = false) {
  const tag = isTh ? 'th' : 'td'
  const colspan = td.colSpan > 1 ? `colSpan="${td.colSpan}"` : ''
  const rowspan = td.rowSpan > 1 ? `rowspan="${td.rowSpan}"` : ''
  let str = `<${tag} data-id="${uuid()}" width="${td.width}" ${colspan + rowspan}>`
  Array.from(td.children || []).forEach((el) => (str += generateBlockStr(el)))
  return str + `</${tag}>`
}

function generateTableRowStr(tds, isTh = false) {
  return tds.reduce((str, td) => str + generateTableTdStr(td, isTh), `<tr data-id="${uuid()}">`) + `</tr>`
}

function getTheadRowsCount(rows) {
  const firstRowTds = Array.from(rows[0].children)
  return firstRowTds.reduce((sum, td) => (td.rowSpan > sum ? td.rowSpan : sum), 1)
}

function generateTableStr(rows, editor) {
  const { annexNumber } = getAnnexIntroductionNumber('table', editor)
  // 1. 初始化，表头
  let str = generateTableCaptionStr(annexNumber)
  const theadRowsCount = getTheadRowsCount(rows)

  rows.forEach((row, i, arr) => {
    if (i === 0) {
      str += '<thead>'
    }

    str += generateTableRowStr(Array.from(row.children), i <= theadRowsCount - 1)

    if (i === theadRowsCount - 1) {
      str += '</thead><tbody>'
    }
    if (i === arr.length - 1) {
      str += '</tbody>'
    }
  })
  return str
}

function getFigureEl(img, editor) {
  const { annexNumber, className } = getAnnexIntroductionNumber('figure', editor)
  const config = {
    'data-id': uuid(),
    class: 'data-content-image-wrapper ' + className,
    'data-block-id': uuid(),
    'data-type': 'figure'
  }
  if (annexNumber) {
    config['data-figure-annex-number'] = annexNumber
  }
  const elm = editor.dom.create('div', config)
  const figureCaption = generateFigureCaptionStr(annexNumber)
  elm.innerHTML = `
    <p class="image-wrapper">
      <img src="${img.src}" />${figureCaption}
    </p>
  `
  return elm
}

function setTableAttribs(el, editor) {
  const { annexNumber, className } = getAnnexIntroductionNumber('table', editor)
  const config = {
    'data-id': uuid(),
    class: 'data-content-table ' + className,
    'data-block-id': uuid(),
    'data-type': 'table',
    border: 1
  }
  if (annexNumber) {
    config['data-table-annex-number'] = annexNumber
  }
  editor.dom.setAttribs(el, config)
}

function setPAttribs(el, editor) {
  editor.dom.setAttribs(el, {
    'data-id': uuid(),
    'data-block-id': uuid(),
    'data-type': 'paragraph',
    style: '',
    class: ''
  })
  el.innerHTML = el.innerText
}

function replacePara(el, editor) {
  const newEl = editor.dom.create('p', {
    'data-id': uuid(),
    'data-block-id': uuid(),
    'data-type': 'paragraph'
  })
  newEl.innerHTML = el.innerText
  editor.dom.replace(newEl, el)
  return newEl.outerHTML
}

function updateUnknownTable(el, editor) {
  const rows = Array.from(el.rows || [])
  if (!rows.length) {
    console.debug('-----updateUnknownTable error----')
    return
  }

  setTableAttribs(el, editor)
  el.innerHTML = generateTableStr(rows, editor)
}

function updateUnknownImg(img, editor) {
  const newImg = getFigureEl(img, editor)
  img.parentNode.replaceChild(newImg, img)
}

function updateUnknownP(el, editor) {
  setPAttribs(el, editor)
}

function checkStyleSpan(el) {
  const { tagName, attributes } = el
  return tagName === 'SPAN' && attributes.length === 1 && attributes[0].name === 'style'
}

function insertContent(content, editor) {
  editor.execCommand('mceInsertContent', false, content)
}

export function pasteUpdatedDOM(htmlStr, editor) {
  const docDom = new DOMParser().parseFromString(htmlStr, 'text/html')
  const insertText = () => {
    editor.getDoc()?.execCommand('insertText', false, docDom.body.innerText.replace(/\r|\n|\r\n/g, ''))
  }
  // 纯文本
  const len = docDom.body?.children?.length

  let tableDom = null
  const tableEl = docDom.body.querySelector('table')
  if (tableEl?.dataset?.type) {
    // 表格
    tableDom = tableEl
  } else if (tableEl?.parentNode?.dataset?.type) {
    // 缩略语表格
    tableDom = tableEl?.parentNode
  }
  if(tableDom?.dataset?.type) {
    if (!checkBeforeInsert(tableDom.dataset.type)) {
      return
    }
  } else if(tableEl) {
    if (!checkBeforeInsert('table')) {
      return
    }
  }

  let figureDom = null
  const imgEl = docDom.body.querySelector('img')
  if (imgEl?.dataset?.type) {
    // 行内图片，行内公式
    figureDom = imgEl
  } else if (imgEl?.parentNode?.dataset?.type) {
    // 裸图
    figureDom = imgEl?.parentNode
  } else if (imgEl?.parentNode?.parentNode?.dataset?.type) {
    // 图片+分组图片，公式
    figureDom = imgEl?.parentNode?.parentNode
  }

  if(figureDom?.dataset?.type) {
    if (!checkBeforeInsert(figureDom.dataset.type)) {
      return
    }
  } else if(imgEl) {
    if (!checkBeforeInsert('figure')) {
      return
    }
  }

  if (len === 0) {
    insertText()
    return
  } else if (len === 1 && docDom.body.children[0].nodeName === 'SPAN') {
    if (docDom.body.children[0]?.children?.[0]?.nodeName === 'TABLE') {
      docDom.body.innerHTML = docDom.body.children[0].innerHTML
    } else {
      insertText()
      return
    }
  }
  // 1. 判断是否有图、表、公式、流程图
  // 如果有，列项中只能粘贴列项、行内元素、纯文本
  // 表格只能粘贴行内元素、纯文本
  // 表注、表脚注、图注、图脚注后只能粘贴相同的内容和行内元素、纯文本
  // 图片只能粘贴行内元素、纯文本
  // 段落处能粘贴任何内容

  // 2. 逐个解析内容并生成新的DOM
  // 2.1 内容来自WORD，需逐个解析，增加id和data-type等属性
  const hasTable = docDom.body.querySelector('table')

  if (len === 1 && docDom.body.children[0].nodeName === 'IMG') {
    updateUnknownImg(docDom.body.children[0], editor)
  }

  for (const el of docDom.body.children) {
    if (el.dataset.id) {
      updateCmosDocFragment(el, editor)
    } else {
      if (tinymce.DOM.is(el, 'table')) {
        updateUnknownTable(el, editor)
      } else if (tinymce.DOM.is(el, 'p')) {
        const imgEl = el.querySelector('img')
        if (imgEl) {
          updateUnknownP(el, editor)
          Message.warning('暂不支持RTF图片粘贴，已过滤处理')
          // updateUnknownImg(el, editor, event) //TODO
        } else {
          updateUnknownP(el, editor)
        }
      } else if (tinymce.DOM.is(el, 'div')) {
        // 纯文本
        if (el.children.length === 1 && el.children[0].nodeName === 'TABLE') {
          updateUnknownTable(el.children[0], editor)
          el.innerHTML = el.children[0].outerHTML
        } else {
          // 多段内容
          Array.from(el.children).forEach((childEl) => {
            checkStyleSpan(childEl) ? editor.dom.replace(childEl.firstChild, childEl) : replacePara(childEl, editor)
          })
        }
        // 如果只有一行，仅粘贴纯文本
        // 如果有多行，则每行用新的 p 标签
        if (docDom.body.children.length === 1) {
          docDom.body.innerHTML = el.innerHTML
        } else {
          replacePara(el, editor)
        }
      } else {
        console.debug('----pasteUpdatedDOM error----')
      }
    }
  }
  // 2.2 内容来自平台自有内容，仅需改变id
  // 3. 将新的DOM树插入到原文处
  const node = editor.selection?.getNode?.()
  if (!node) {
    console.debug('----error----')
    return
  }
  // 是否不允许在列项中插入(列项不能被其他结构化数据打断)
  const inBullet = node.dataset.type === 'item_list' && node.nextElementSibling?.dataset?.type === 'item_list'
  const invalidEl = docDom.body.querySelector('table,[data-type="formula"],[data-type="figure"]')
  if (invalidEl && inBullet) {
    return Message.warning({
      message: '列项中暂不支持插入表格、图片、公式',
      showClose: true
    })
  }

  editor.insertContent(Array.from(docDom.body.children).reduce((pre, el) => pre + el.outerHTML, ''))

  setTimeout(() => {
    if (hasTable) {
      refreshTableNumbers(editor)
    }
    if (docDom.body.querySelector('img')) {
      refreshFigureNumbers(editor)
    }
  })
}
